package com.gmcloud.common.security.feign;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.gmcloud.common.core.constant.SecurityConstants;
import com.gmcloud.common.core.utils.WebUtil;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Optional;

/**
 * @author zl.sir
 * @version 1.0
 * @since 2022/8/17 13:08
 * feign 拦截器将本服务的token 通过copyToken的形式传递给下游服务
 */
public class GmOAuthRequestInterceptor implements RequestInterceptor {
    private final BearerTokenResolver tokenResolver;


    public GmOAuthRequestInterceptor(BearerTokenResolver tokenResolver) {
        this.tokenResolver = tokenResolver;
    }

    /**
     * Create a template with the header of provided name and extracted extract </br>
     * <p>
     * 1. 如果使用 非web 请求，header 区别 </br>
     * <p>
     * 2. 根据authentication 还原请求token
     *
     * @param template
     */
    @Override
    public void apply(RequestTemplate template) {
        Collection<String> fromHeader = template.headers().get(SecurityConstants.FROM);
        // 带from 请求直接跳过
        if (CollUtil.isNotEmpty(fromHeader) && fromHeader.contains(SecurityConstants.FROM_IN)) {
            return;
        }

        // 非web 请求直接跳过
        HttpServletRequest request = WebUtil.getRequest();
        Enumeration<String> headerNames = request.getHeaderNames();
        if (headerNames != null) {
            while (headerNames.hasMoreElements()) {
                String name = headerNames.nextElement();
                String values = request.getHeader(name);
                template.header(name, values);

            }
        }

        // 避免请求参数的 query token 无法传递
        String token = tokenResolver.resolve(request);
        if (CharSequenceUtil.isBlank(token)) {
            return;
        }
        template.header(HttpHeaders.AUTHORIZATION, String.format("%s %s", OAuth2AccessToken.TokenType.BEARER, token));

    }
}
